using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Forms;

namespace VisionarySystems.TimeRegi.Model.TimePeriods
{
	public class TimeSlot : ITimePeriode, IEnumerable<TimeSlot>
	{
		#region Private Members
		int m_Idx;
		DateTime m_Start;
		DateTime m_Stop;
		TimeSlotTypes m_Type;
		private TimePeriodeID m_ID;
		private static int m_UniqueIndex = 1;

		#endregion

		#region Ctor

		public TimeSlot(int Idx, DateTime Start, DateTime Stop, TimeSlotTypes Type)
		{
			m_Idx = Idx;
			m_Start = Start;
			m_Stop = Stop;
			m_Type = Type;
			ID = new TimePeriodeID(GetUniqueIndex(), TimePeriodeType.TimeSlot);
		}

		private int GetUniqueIndex()
		{
			return m_UniqueIndex++;
		}

		#endregion

		#region Properties

		public TimePeriodeID ID
		{
			get { return m_ID; }
			set { m_ID = value; }
		}

		public TimeSpan BrakeTime { get; set; }

		public DateTime Start
		{
			get { return m_Start; }
			set { m_Start = value; }
		}

		public DateTime Stop
		{
			get { return m_Stop; }
			set { m_Stop = value; }
		}

		public int Idx { get { return m_Idx; } }

		public TimeSpan WorkedTime
		{
			get
			{
				return m_Stop.Subtract(m_Start);
			}
		}

		public int TimeSlotCount
		{
			get
			{
				return 1;
			}

		}

		public int SubClassCount
		{
			get
			{
				return 0;
			}
		}

		public int Year
		{
			get { return m_Start.Year; }
		}

		public int Month
		{
			get { return m_Start.Month; }
		}

		public int Week
		{
			get
			{
				int weekNo = 0;
				DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
				if (dfi != null)
				{
					Calendar cal = dfi.Calendar;

					weekNo = cal.GetWeekOfYear(m_Start,
												   dfi.CalendarWeekRule,
												   dfi.FirstDayOfWeek);
				}
				return weekNo;
			}
		}

		public DateTime Date
		{
			get { return m_Start.Date; }
		}


		#endregion

		#region Public methods

		public static string GetTime(DateTime d)
		{
			return string.Format("{0:D2}:{1:D2}", d.Hour, d.Minute);
		}

		public static string GetHours(TimeSpan ts)
		{
			return string.Format("{0:D1},{1:D1}", (int)(ts.TotalHours), 10 * ts.Minutes / 60);
			//return string.Format("{0:D1},{1:D1}", ts.Hours, (int)(10 * ts.Minutes / 60));
		}

		public TreeNode GetNode()
		{
			var node = new TreeNode(ToString());
			node.Tag = ID;
			return node;
		}

		public ITimePeriode GetTimePeriode(TimePeriodeID FindID)
		{
			ITimePeriode result = null;
			if (FindID.Equals(ID))
				result = this;
			return result;
		}

		IEnumerator<ITimePeriode> IEnumerable<ITimePeriode>.GetEnumerator()
		{
			yield break;
		}

		public override string ToString()
		{
			return string.Format("{0} - {1} ({2})", GetTime(m_Start), GetTime(m_Stop), GetHours(WorkedTime));
		}

		public void Add(IEnumerable<TimeSlot> TimeSlots)
		{
			throw new ArgumentException("It is not allowed to add a period to a TimeSlot");
		}

		/// <summary>
		/// It is not possible to assemble a timeslot
		/// </summary>
		/// <param name="NewTimeSlots"></param>
		/// <param name="RemovedIndexes"></param>
		public bool AssembleTimeslots(out List<TimeSlot> NewTimeSlots, out List<int> RemovedIndexes)
		{
			RemovedIndexes = new List<int>();
			NewTimeSlots = new List<TimeSlot>();
			return false;
		}

		public TimePeriodeType GetTypeID()
		{
			return TimePeriodeType.TimeSlot;
		}

		public IEnumerator<TimeSlot> GetEnumerator()
		{
			yield return this;
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			yield return this;
		}

		public IEnumerable<TimeSlot> TimeSlots()
		{
			yield return this;
		}

		public void GetTimePeriode(DateTime StartTime, DateTime EndTime, ref ITimePeriode TimePeriod)
		{
			var result = new List<TimeSlot>();
			if ((m_Start >= StartTime) && (m_Stop <= EndTime))
			{
				result.Add(this);
				TimePeriod.Add(result);
			}
		}

		public void GetWorkingDates(ref List<DateTime> WorkingDates)
		{
		}

		public bool DeleteTimeslots(ref List<int> RemovedIndexes)
		{
			RemovedIndexes.Add(Idx);
			return true;
		}

		public void DeleteTimePeriode(ITimePeriode Periode)
		{
			throw new NotSupportedException("Cant delete periodes in a timeslot");
		}

		public void DeleteTimeSlot(int Idx)
		{
			throw new NotSupportedException("Cant delete a timeslot in a timeslot");
		}

		#endregion
	}
}